import tkinter as tk
from tkinter import messagebox
import math
import os

def create_widgets():
    global display
    display = tk.Entry(root, font=("等线", 24), bd=10, insertwidth=2, width=30, borderwidth=4, justify="right")
    display.grid(row=0, column=0, columnspan=5, pady=10, padx=10)

    create_special_buttons()
    create_main_buttons()
    create_history_memory_section()

def create_special_buttons():
    special_buttons = [
        ('2ⁿᵈ', 1, 0), ('π', 1, 1), ('e', 1, 2), ('C', 1, 3), ('⌫', 1, 4),
        ('x²', 2, 0), ('1/x', 2, 1), ('|x|', 2, 2), ('exp', 2, 3), ('mod', 2, 4),
        ('√x', 3, 0), ('(', 3, 1), (')', 3, 2), ('n!', 3, 3), ('÷', 3, 4),
        ('M+', 4, 4), ('MR', 5, 4), ('MC', 6, 4)
    ]
    for (text, row, col) in special_buttons:
        add_button(text, row, col, height=2)

def create_main_buttons():
    buttons = [
        ('7', 4, 0), ('8', 4, 1), ('9', 4, 2), ('×', 4, 3),
        ('4', 5, 0), ('5', 5, 1), ('6', 5, 2), ('-', 5, 3),
        ('1', 6, 0), ('2', 6, 1), ('3', 6, 2), ('+', 6, 3),
        ('±', 7, 0), ('0', 7, 1), ('.', 7, 2), ('=', 7, 3, 1, 2)
    ]
    for button in buttons:
        if len(button) == 5:
            add_button(button[0], button[1], button[2], button[3], button[4], height=3)
        else:
            add_button(button[0], button[1], button[2], height=2)

def create_history_memory_section():
    global history_listbox, memory_listbox
    history_label = tk.Label(root, text="历史记录", font=("Arial", 12))
    history_label.grid(row=1, column=5, columnspan=2, sticky="w")
    history_listbox = tk.Listbox(root, height=10)
    history_listbox.grid(row=2, column=5, rowspan=3, sticky="ns")

    memory_label = tk.Label(root, text="记忆", font=("Arial", 12))
    memory_label.grid(row=5, column=5, columnspan=2, sticky="w")
    memory_listbox = tk.Listbox(root, height=10)
    memory_listbox.grid(row=6, column=5, rowspan=3, sticky="ns")

def add_button(text, row, col, rowspan=1, colspan=1, height=2):
    button = tk.Button(root, text=text, padx=20, pady=10, font=("Arial", 14), height=height, command=lambda t=text: on_button_click(t))
    button.grid(row=row, column=col, rowspan=rowspan, columnspan=colspan, sticky="nsew", padx=5, pady=5)

def on_button_click(char):
    global current_input, second_mode
    if char == "=":
        calculate()
    elif char == "C":
        clear()
    elif char == "±":
        negate()
    elif char == "⌫":
        backspace()
    elif char == '2ⁿᵈ':
        toggle_second_mode()
    elif char in ["π", "e"]:
        add_constant(char)
    elif char in ["x²", "√x", "1/x", "|x|", "exp", "n!"]:
        perform_unary_operation(char)
    elif char == "mod":
        perform_mod()
    elif char == "M+":
        memory_store()
    elif char == "MR":
        memory_recall()
    elif char == "MC":
        memory_clear()
    else:
        display.insert(tk.END, char)
        current_input += char

def calculate():
    global current_input
    try:
        expression = current_input.replace('×', '*').replace('÷', '/')
        result = eval(expression)
        display.delete(0, tk.END)
        display.insert(tk.END, str(result))
        save_history(current_input + "=" + str(result))
        current_input = str(result)
    except Exception as e:
        messagebox.showerror("错误", "无效输入")
        clear()

def clear():
    global current_input
    display.delete(0, tk.END)
    current_input = ""

def negate():
    current_value = display.get()
    if current_value:
        if current_value.startswith('-'):
            display.delete(0)
        else:
            display.insert(0, '-')

def backspace():
    global current_input
    current_input = current_input[:-1]
    display.delete(len(display.get())-1, tk.END)

def toggle_second_mode():
    global second_mode
    second_mode = not second_mode
    if second_mode:
        special_buttons[5] = ('x³', 2, 0)
        special_buttons[10] = ('∛x', 3, 0)
    else:
        special_buttons[5] = ('x²', 2, 0)
        special_buttons[10] = ('√x', 3, 0)
    for button in special_buttons:
        add_button(button[0], button[1], button[2], height=2)

def add_constant(constant):
    global current_input
    if constant == "π":
        display.insert(tk.END, str(math.pi))
        current_input += str(math.pi)
    elif constant == "e":
        display.insert(tk.END, str(math.e))
        current_input += str(math.e)

def perform_unary_operation(operation):
    global current_input
    current_value = display.get()
    if current_value:
        try:
            if operation == "x²":
                result = float(current_value) ** 2
            elif operation == "x³":
                result = float(current_value) ** 3
            elif operation == "√x":
                result = math.sqrt(float(current_value))
            elif operation == "∛x":
                result = float(current_value) ** (1/3)
            elif operation == "1/x":
                result = 1 / float(current_value)
            elif operation == "|x|":
                result = abs(float(current_value))
            elif operation == "exp":
                result = math.exp(float(current_value))
            elif operation == "n!":
                result = math.factorial(int(current_value))
            display.delete(0, tk.END)
            display.insert(tk.END, str(result))
            current_input = str(result)
        except Exception as e:
            messagebox.showerror("错误", "无效输入")

def perform_mod():
    global current_input
    current_value = display.get()
    if 'mod' in current_value:
        try:
            operands = current_value.split('mod')
            if len(operands) == 2:
                left_operand = eval(operands[0])
                right_operand = eval(operands[1])
                result = left_operand % right_operand
                display.delete(0, tk.END)
                display.insert(tk.END, str(result))
                current_input = str(result)
            else:
                messagebox.showerror("错误", "无效输入")
        except Exception as e:
            messagebox.showerror("错误", "无效输入")
    else:
        current_input += ' mod '
        display.insert(tk.END, ' mod ')

def save_history(entry):
    global history_file
    with open(history_file, "a") as file:
        file.write(entry + "\n")
    history_listbox.insert(tk.END, entry)

def load_history():
    global history_file
    if os.path.exists(history_file):
        with open(history_file, "r") as file:
            history = file.readlines()
        for entry in history:
            history_listbox.insert(tk.END, entry.strip())

def save_memory(value):
    global memory_file
    with open(memory_file, "a") as file:
        file.write(value + "\n")
    memory_listbox.insert(tk.END, value)

def load_memory():
    global memory_file
    if os.path.exists(memory_file):
        with open(memory_file, "r") as file:
            memory = file.readlines()
        for value in memory:
            memory_listbox.insert(tk.END, value.strip())

def memory_store():
    current_value = display.get()
    if current_value:
        save_memory(current_value)

def memory_recall():
    global memory
    if memory:
        last_value = memory[-1].strip()
        display.delete(0, tk.END)
        display.insert(tk.END, last_value)
        current_input = last_value

def memory_clear():
    global memory, memory_file
    memory = []
    memory_listbox.delete(0, tk.END)
    if os.path.exists(memory_file):
        os.remove(memory_file)

if __name__ == "__main__":
    root = tk.Tk()
    root.title("计算器")
    root.geometry("700x710")
    root.resizable(False, False)
    history_file = "history.txt"
    memory_file = "memory.txt"
    current_input = ""
    history = []
    memory = []
    second_mode = False

    create_widgets()
    load_history()
    load_memory()

    root.mainloop()
